﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Validation.Impl;

namespace StyleMVVM.Validation
{
	public sealed class ValidationRuleResult : IValidationRuleResult
	{
		private readonly List<ValidationRuleResultPart> resultParts;
		private readonly WeakReference validationObject;

		public ValidationRuleResult(IValidationRule rule, RuleExecutionContext executionContext)
		{
			validationObject = new WeakReference(executionContext.ValidationObject);

			Namespace = rule.Namespace;
			RuleName = rule.Name;
			DisplayName = rule.DisplayName;
			State = executionContext.State;
			Message = executionContext.Message;

			resultParts = new List<ValidationRuleResultPart>();
			IEnumerable<IValidationRuleResultPart> newParts = executionContext.ResultParts();

			if (newParts != null)
			{
				foreach (IValidationRuleResultPart resultPart in newParts)
				{
					resultParts.Add(new ValidationRuleResultPart(this, resultPart.PartName, resultPart.State, resultPart.Message));
				}
			}
		}

		public string Namespace { get; private set; }

		public string RuleName { get; private set; }

		public object ValidationObject
		{
			get { return validationObject.Target; }
		}

		public string DisplayName { get; private set; }

		public ValidationState State { get; private set; }

		public string Message { get; private set; }

		public string RootPropertyPath { get; set; }

		public IEnumerable<IValidationRuleResultPart> ResultParts()
		{
			return resultParts;
		}

		public override int GetHashCode()
		{
			object target = ValidationObject;

			if (target != null)
			{
				return (RuleName + target.GetType().FullName).GetHashCode();
			}

			return RuleName.GetHashCode();
		}

		public static bool AreEqual(IValidationRuleResult leftSide, IValidationRuleResult rightSide)
		{
			if (leftSide != null)
			{
				if (leftSide.Namespace != rightSide.Namespace)
				{
					return false;
				}

				if (leftSide.RuleName != rightSide.RuleName)
				{
					return false;
				}

				if (leftSide.ValidationObject != rightSide.ValidationObject)
				{
					return false;
				}
				if (leftSide.Message != rightSide.Message)
				{
					return false;
				}

				if (leftSide.State != rightSide.State)
				{
					return false;
				}

				if (leftSide.DisplayName != rightSide.DisplayName)
				{
					return false;
				}

				int count = 0;
				IEnumerable<IValidationRuleResultPart> rightSideParts = rightSide.ResultParts();

				foreach (IValidationRuleResultPart validationRuleResultPart in leftSide.ResultParts())
				{
					if (!rightSideParts.Contains(validationRuleResultPart))
					{
						return false;
					}

					count++;
				}

				if (count != rightSideParts.Count())
				{
					return false;
				}

				return true;
			}

			return false;
		}
	}
}